/*****************************************************************************/
/*!	\file		MainServer.c
 *	\brief		C Source code file for the Example IEC61850 Server using the YX-PIS
 *				This server has a CSWI, GGIO, Phase Measurement and a Curve Description Array
 *				The server publishes GOOSE packets containing the CSWI and GGIO stVal and q values
 *				Buffered and UnBuffered reports are available for CSWI, GGIO, Phase Measurement and
 *				a Curve Description Array to the client to get data from the server.
 *				All points can also bee read by a client.
 *
 *	\par		Dalian Yunxing Tech Co., Ltd.
 *
 *				Dalian, China
 *				Phone   : +86 (411) 8825 4852
 *				Email   : yx@yunxing.tech
 */
/*****************************************************************************/

#if defined (__PARADIGM__)|| defined(_SC1x5_)
// for BECK we need the clib.h
#include <clib.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "MainServer.h"
#include "PrintView.h"
#include "PIS10CreateServerClient.h"
#include "UserInput.h"
#include "LocalData.h"
#include "IEC61850Functions.h"
#include "IEC61850API.h"

#ifndef NO_SSL
#include <openssl/ssl.h>
#include <openssl/err.h>
#endif

#include "log4c.h"


static char* s_cidFile = NULL;

int main(int argc, char** argv)
{
	char continueMainLoop = 'y';
	enum UserCommands usrCommand = COMMAND_NONE;	// the User command to execute
	IEC61850_ErrorCode IEC61850Error = S_OK;	// variable to hold the IEC61850_ErrorCode
	S32 int32Val = 0;	// temporary value to hold user input
	S8 int8Val = 0;	// temporary value to hold user input
	Float32 f32Val = 0.0;	// temporary value to hold user input
	CrvPts CrvPtsVal = { 0 };	// temporary value to hold user input

#if defined (__PARADIGM__) || defined(_SC1x5_)
	// for BECK Set STDIO focus to application
	BIOS_Set_Focus(FOCUS_APPLICATION);
#endif

#ifndef NO_SSL
	SSL_library_init();
	OpenSSL_add_all_algorithms();
	SSL_load_error_strings();
#endif

	LOG_Init("log4c-mms-server.xml");
	LOG_Logger("mms.server");

	LOG_INFO("IEC61850 mms-server Example from yunxing.tech YX-PIS: %s\n", IEC61850_GetLibraryVersion());

	if (argc >= 2) {
		s_cidFile = argv[1];
		LOG_INFO("cid = %s", s_cidFile);
	}

	IEC61850Error = setupIEC61850Server();

	if (IEC61850Error == S_OK) { //If the server stated successfully
		do {
			PrintServerFullView();

			usrCommand = GetServerCommandFromUser(); /* Get the User Input */

			switch (usrCommand) {
			case COMMAND_EXIT:
				continueMainLoop = 'n'; /* Set the Loop to exit */
				break;
			case COMMAND_MMS_GET_CONNECTED_SERVER_LIST:
				GetConnectionsList();
				break;
			case COMMAND_UPDATE_MMXU_PHSA:
				/* Get a value from user */
				int32Val = GetInteger32FromUser();
				/* Do the Update with the value*/
				UpdateMMXUPhsAMagi(int32Val);
				break;
			case COMMAND_UPDATE_MMXU_PHSB:
				/* Get a value from user */
				int32Val = GetInteger32FromUser();
				/* Do the Update with the value*/
				UpdateMMXUPhsBMagi(int32Val);
				break;
			case COMMAND_UPDATE_MMXU_PHSC:
				/* Get a value from user */
				int32Val = GetInteger32FromUser();
				/* Do the Update with the value*/
				UpdateMMXUPhsCMagi(int32Val);
				break;
			case COMMAND_UPDATE_PDIF_XVAL:
				/* Get Index from User */
				int8Val = GetIndexForArray();
				/* Get a value from user */
				f32Val = GetFloat32FromUser();
				/* Get current CrvPts to update */
				CrvPtsVal = GetPDIFCrvPts(int8Val);
				CrvPtsVal.xVal = f32Val;
				/* Do the Update with the value at the index*/
				UpdatePDIFCrvPts(CrvPtsVal, int8Val);
				break;
			case COMMAND_UPDATE_PDIF_YVAL:
				/* Get Index from User */
				int8Val = GetIndexForArray();
				/* Get a value from user */
				f32Val = GetFloat32FromUser();
				/* Get current CrvPts to update */
				CrvPtsVal = GetPDIFCrvPts(int8Val);
				CrvPtsVal.yVal = f32Val;
				/* Do the Update with the value at the index*/
				UpdatePDIFCrvPts(CrvPtsVal, int8Val);
				break;
			case COMMAND_UPDATE_TTNS_TNSSV1:
				/* Get a value from user */
				f32Val = GetFloat32FromUser();
				/* Do the Update with the value*/
				UpdateTTNSTnsSv1Magf(f32Val);
				break;
			case COMMAND_UPDATE_TTNS_TNSSV2:
				/* Get a value from user */
				f32Val = GetFloat32FromUser();
				/* Do the Update with the value*/
				UpdateTTNSTnsSv2Magf(f32Val);
				break;
			case COMMAND_UPDATE_TTNS_TNSSV3:
				/* Get a value from user */
				f32Val = GetFloat32FromUser();
				/* Do the Update with the value*/
				UpdateTTNSTnsSv3Magf(f32Val);
				break;
			case COMMAND_INNER_UNIT_TEST:
				InnerTestServer();
				break;
			default:
				break;
			}
		} while (continueMainLoop == 'y');
	}

	printf("Stopping IEC61850 Server \n");
	StopMyServerClient(); // Stop server if running
	printf("Freeing IEC61850 Server \n");
	FreeMyServerClient(); // Free server if running

	// Allow the program to pause and let the user see any exit messages
	printf("\nIEC61850 Server Example has ended, press enter to exit\n");
	getchar();

#if defined (__PARADIGM__)|| defined(_SC1x5_)
	// for BECK Set STDIO focus back to both for terminal and Applications
	BIOS_Set_Focus(FOCUS_BOTH);
#endif

	return 0;
}

/*!
 * \brief         This function Creates, Loads and Starts the IEC61850 Server
 *
 *   \ingroup       Setup Function
 *
 *   \param[in]     Var     DESC
 *
 *   \return        S_OK on success,
 *   \return        otherwise the relevant IEC61850_ErrorCode
 */
IEC61850_ErrorCode setupIEC61850Server()
{
	IEC61850_ErrorCode result = IEC61850_ERROR_SERVICE_FAILED;

	// ensure that the API header files and the library are version-compatible.
	if (memcmp(IEC61850_GetLibraryVersion(), YX_PIS_VERSION, sizeof(YX_PIS_VERSION)) == 0) {
		result = CreateServer(IEC61850_OPTION_NONE);

		if (result == S_OK) {
			result = LoadSCLFile(s_cidFile ? s_cidFile : "./mms-cid/server.cid");
			if (result == S_OK) {
				result = StartMyServerClient();
			} else if (result == IEC61850_ERROR_LICENCE_INVALID) {
				printf("IEC61850 License for this device is invalid\n");
			}
		} else if (result == IEC61850_ERROR_LICENCE_INVALID) {
			printf("IEC61850 License for this device is invalid\n");
		}
	} else {
		printf("Version Mismatch: YX-PIS IEC61850API.h Version = %s , YX-PIS Library Version = %s\n", YX_PIS_VERSION, IEC61850_GetLibraryVersion());
	}
	return result;
}
